using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using bitzhuwei.Compiler;

namespace bitzhuwei.AnsiCFormat {
    /// <summary>
    /// Correspond to the Vn node direct_abstract_declarator in the grammar(AnsiC).
    /// </summary>
    internal partial class Vndirect_abstract_declarator : IFullFormatter {
        // [158]=direct_abstract_declarator : '(' abstract_declarator ')' ;
        // [159]=direct_abstract_declarator : '[' ']' ;
        // [160]=direct_abstract_declarator : '[' constant_expression ']' ;
        // [161]=direct_abstract_declarator : direct_abstract_declarator '[' ']' ;
        // [162]=direct_abstract_declarator : direct_abstract_declarator '[' constant_expression ']' ;
        // [163]=direct_abstract_declarator : '(' ')' ;
        // [164]=direct_abstract_declarator : '(' parameter_type_list ')' ;
        // [165]=direct_abstract_declarator : direct_abstract_declarator '(' ')' ;
        // [166]=direct_abstract_declarator : direct_abstract_declarator '(' parameter_type_list ')' ;

        public readonly Item first0;
        public readonly List<Item> list0 = new();

        private readonly TokenRange _scope;
        public TokenRange Scope => _scope;

        public void Format(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

        public void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
            {
                context.PrintBlanksAnd(this.first0, preConfig, writer);
            }
            var first = true;
            var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
            for (var i = 0; i < this.list0.Count; i++) {
                var item0 = this.list0[i];
                if (first) {
                    context.PrintCommentsBetween(this.first0, item0, config, writer);
                    first = false;
                }
                else {
                    context.PrintCommentsBetween(this.list0[i - 1], item0, config, writer);
                }
                context.PrintBlanksAnd(item0, config, writer);
            }
        }

        public IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }
        /// <summary>
        /// [158]=direct_abstract_declarator : '(' abstract_declarator ')' ;
        /// </summary>
        /// <param name="first2"></param>
        /// <param name="first1"></param>
        /// <param name="first0"></param>
        public Vndirect_abstract_declarator(Token first2, Vnabstract_declarator first1, Token first0) {
            this.first0 = new abs_(first2, first1, first0);
            this._scope = new TokenRange(this.first0);
        }
        /// <summary>
        /// [159]=direct_abstract_declarator : '[' ']' ;
        /// [160]=direct_abstract_declarator : '[' constant_expression ']' ;
        /// </summary>
        /// <param name="first2"></param>
        /// <param name="first1"></param>
        /// <param name="first0"></param>
        public Vndirect_abstract_declarator(Token first2, Vnconstant_expression? first1, Token first0) {
            this.first0 = new const_(first2, first1, first0);
            this._scope = new TokenRange(this.first0);
        }
        /// <summary>
        /// [163]=direct_abstract_declarator : '(' ')' ;
        /// [164]=direct_abstract_declarator : '(' parameter_type_list ')' ;
        /// </summary>
        /// <param name="first2"></param>
        /// <param name="first1"></param>
        /// <param name="first0"></param>
        public Vndirect_abstract_declarator(Token first2, Vnparameter_type_list? first1, Token first0) {
            this.first0 = new params_(first2, first1, first0);
            this._scope = new TokenRange(this.first0);
        }

        /// <summary>
        /// [161]=direct_abstract_declarator : direct_abstract_declarator '[' ']' ;
        /// [162]=direct_abstract_declarator : direct_abstract_declarator '[' constant_expression ']' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(Token r2, Vnconstant_expression? r1, Token r0) {
            this.list0.Add(new const_(r2, r1, r0));
        }
        /// <summary>
        // [165]=direct_abstract_declarator : direct_abstract_declarator '(' ')' ;
        // [166]=direct_abstract_declarator : direct_abstract_declarator '(' parameter_type_list ')' ;
        /// </summary>
        /// <param name="r2"></param>
        /// <param name="r1"></param>
        /// <param name="r0"></param>
        internal void Add(Token r2, Vnparameter_type_list? r1, Token r0) {
            this.list0.Add(new params_(r2, r1, r0));
        }


        public abstract class Item : IFullFormatter {
            public abstract TokenRange Scope { get; }

            public abstract void Format(TextWriter writer, FormatContext context);
            public abstract void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context);
            public abstract IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context);
        }
        public class abs_ : Item {
            private readonly Token first2;
            private readonly Vnabstract_declarator first1;
            private readonly Token first0;

            public abs_(Token first2, Vnabstract_declarator first1, Token first0) {
                this.first2 = first2;
                this.first1 = first1;
                this.first0 = first0;
            }

            public override TokenRange Scope => throw new NotImplementedException();

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(first2, preConfig, writer);
                var config = new BlankConfig();
                context.PrintCommentsBetween(first2, first1, config, writer);
                context.PrintBlanksAnd(first1, config, writer);
                context.PrintCommentsBetween(first1, first0, config, writer);
                context.PrintBlanksAnd(first0, config, writer);
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class const_ : Item {
            private readonly Token first2;
            private readonly Vnconstant_expression? first1;
            private readonly Token first0;

            public const_(Token first2, Vnconstant_expression? first1, Token first0) {
                this.first2 = first2;
                this.first1 = first1;
                this.first0 = first0;
            }

            public override TokenRange Scope => throw new NotImplementedException();

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(first2, preConfig, writer);
                var config = new BlankConfig();
                if (first1 != null) {
                    context.PrintCommentsBetween(first2, first1, config, writer);
                    context.PrintBlanksAnd(first1, config, writer);
                    context.PrintCommentsBetween(first1, first0, config, writer);
                }
                else {
                    context.PrintCommentsBetween(first2, first0, config, writer);
                    context.PrintBlanksAnd(first0, config, writer);
                }
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
        public class params_ : Item {
            private readonly Token first2;
            private readonly Vnparameter_type_list? first1;
            private readonly Token first0;

            public params_(Token first2, Vnparameter_type_list? first1, Token first0) {
                this.first2 = first2;
                this.first1 = first1;
                this.first0 = first0;
            }

            public override TokenRange Scope => throw new NotImplementedException();

            public override void Format(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }

            public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
                context.PrintBlanksAnd(first2, preConfig, writer);
                var config = new BlankConfig();
                if (first1 != null) {
                    context.PrintCommentsBetween(first2, first1, config, writer);
                    context.PrintBlanksAnd(first1, config, writer);
                    context.PrintCommentsBetween(first1, first0, config, writer);
                }
                else {
                    context.PrintCommentsBetween(first2, first0, config, writer);
                    context.PrintBlanksAnd(first0, config, writer);
                }
            }

            public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
                throw new NotImplementedException();
            }
        }
    }
}
